﻿#-------------------------------------------------------------------------------
# Copyright 2011 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
#$Id$
#$Author$
#$Date$
#$Rev$
#$URL$
#-------------------------------------------------------------------------------

#当程序执行的时候，可能会出现一些异常现象，这个可能是会存在的。例如，你在读文件的时候，而那个文件不存在。此时，我们可以用异常来处理。
#1. 错误
#我们来做个简单的测试，我们故意把print方法写出Print。
#>>> Print("Hello world")
#Traceback (most recent call last):
#  File "<pyshell#0>", line 1, in <module>
#    Print("Hello world")
#NameError: name 'Print' is not defined
#>>>
#系统会抛出NameError异常。

#2. try..except
#我们可以用try..except处理异常。

try:
    f = open("test.txt")
    f.close()
except(IOError):
    print("The file is not exist.")
except:
    print("Some error occurred.")

print("Done")

#运行结果：
#The file is not exist.
#Done

#3. 引发异常
#你可以用raise语句来引发异常。我们先自定义一个ShortInputError异常，需要继承Exception类。
class ShortInputError(Exception):
    '''A user-defined exception class.'''
    def __init__(self, length, atleast):
        Exception.__init__(self)
        self.length = length
        self.atleast = atleast

try:
    s = input("Enter something -->")
    if len(s) < 3:
        raise(ShortInputError(len(s), 3))
    #Other work can continue as usual here
except(EOFError):
    print("Why did you do an EOF on me?")
except ShortInputError as e:
    print("ShortInputError: The input was of length %d, \
was expecting at least %d" % (e.length, e.atleast))
else:
    print("No exception was raised.")

#输入两个字符运行结果：
#>>>
#Enter something -->tr
#ShortInputError: The input was of length 2, was expecting at least 3
#>>>
#输入三个字符以上运行结果：
#>>>
#Enter something -->test
#No exception was raised.
#>>>

#4. try..finally
#假如你在读一个文件的时候，希望在无论异常发生与否的情况下都关闭文件，该怎么做呢？这可以使用finally块来完成。注意，在一个try块下，你可以同时使用except从句和finally块。如果你要同时使用它们的话，需要把一个嵌入另外一个。
import time

try:
    f = open("poem.txt")
    while True: # our usual file-reading idiom
        line = f.readline()
        if len(line) == 0:
            break
        time.sleep(2)
        print(line),
finally:
    f.close()
    print("Cleaning up...closed the file")

#运行结果：
#>>>
#Programming is fun
#When the work is done
#if you wanna make your work also fun:
#    use Python!
#Cleaning up...closed the file
#>>>

def divide(x, y):
    try:
        result = x/ y
    except ZeroDivisionError:
        print("Division by zero!")
    else:
        print("result is", result)
    finally:
        print("executing finally clause")

#测试结果：
#>>> divide(2, 1)
#result is 2.0
#executing finally clause
#>>> divide(2, 0)
#Division by zero!
#executing finally clause
#>>> divide("2", "1")
#executing finally clause
#Traceback (most recent call last):
#  File "<pyshell#13>", line 1, in <module>
#    divide("2", "1")
#  File "<pyshell#10>", line 3, in divide
#    result = x/ y
#TypeError: unsupported operand type(s) for /: 'str' and 'str'
#>>>